<?php
/**
 * Tool,common helper
 * @package
 * @copyright 56.com
 */
class GeoTool {
	/**
	 * 获取区域记录
	 * @param  boolean $ip [description]
	 * @return [type]      [description]
	 */
	public static function getAreaLogByIp($ip = false) {
		$array = '';
		$ip = $ip ? $ip : g::ip();
		$city = GeoTool::convertIp($ip);

		if (preg_match('/局域网/', $city)) {
			return $array;
		}
		if ((is_array($city) && $city['err'] === true)) {
			return $array;
		}
		
		$array = str_ireplace('CZ88.NET', '', $city);
		$array = trim($array);
		return $array;
	}

	/**
	 * GetCityNameByIp
	 *
	 * @static
	 * @access public
	 * @return void
	 */
	public static function getAreaNameByIp($ip = false) {
		$array = array();
		$ip = $ip ? $ip : g::ip();
		$city = GeoTool::convertIp($ip);

		if (preg_match('/局域网/', $city)) {
			return $array;
		}
		if ((is_array($city) && $city['err'] === true)) {
			return $array;
		}
		$city = explode('市', $city);
		if ($city[0]) {
			$array = explode('省', $city[0]);
		}
		return $array;
	}

	/**
	 * convertIp
	 * example :
	 $cityName = Tool::convertIp("119.145.139.232");
	 *
	 * @param string $ip
	 * @param bloen $onlyCity
	 * @static
	 * @access public
	 * @return void
	 */
	public static function convertIp($ip = '', $onlyCity = true) {

		$ipdatafile = str_replace("\\", "/", dirname(dirname(__FILE__))) . "/ip_data/" . (empty(Core::$configs['ip_data_file'])?'ipb_modify.dat':Core::$configs['ip_data_file']);
		
		$fd = null;
		try {
			$fd = fopen($ipdatafile, 'rb');
			if (!$fd) {
				return array('err' => true, 'msg' => '- Invalid IP data file');
			}
		} catch ( Exception $e ) {
			return array('err' => true, 'msg' => '- Invalid IP data file');
		}

		$ip = explode('.', $ip);
		$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];

		if (!($DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4)))
			return array('err' => true, 'msg' => '- empty IP data file');
		@$ipbegin = implode('', unpack('L', $DataBegin));
		if ($ipbegin < 0)
			$ipbegin += pow(2, 32);
		@$ipend = implode('', unpack('L', $DataEnd));
		if ($ipend < 0)
			$ipend += pow(2, 32);
		$ipAllNum = ($ipend - $ipbegin) / 7 + 1;

		$BeginNum = $ip2num = $ip1num = 0;
		$ipAddr1 = $ipAddr2 = '';
		$EndNum = $ipAllNum;

		while ($ip1num > $ipNum || $ip2num < $ipNum) {
			$Middle = intval(($EndNum + $BeginNum) / 2);

			fseek($fd, $ipbegin + 7 * $Middle);
			$ipData1 = fread($fd, 4);
			if (strlen($ipData1) < 4) {
				fclose($fd);
				return array('err' => true, 'msg' => '- System Error');
			}
			$ip1num = implode('', unpack('L', $ipData1));
			if ($ip1num < 0)
				$ip1num += pow(2, 32);

			if ($ip1num > $ipNum) {
				$EndNum = $Middle;
				continue;
			}

			$DataSeek = fread($fd, 3);
			if (strlen($DataSeek) < 3) {
				fclose($fd);
				return array('err' => true, 'msg' => '- System Error');
			}
			$DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
			fseek($fd, $DataSeek);
			$ipData2 = fread($fd, 4);
			if (strlen($ipData2) < 4) {
				fclose($fd);
				return array('err' => true, 'msg' => '- System Error');
			}
			$ip2num = implode('', unpack('L', $ipData2));
			if ($ip2num < 0)
				$ip2num += pow(2, 32);

			if ($ip2num < $ipNum) {
				if ($Middle == $BeginNum) {
					fclose($fd);
					return array('err' => true, 'msg' => '- Unknown');
				}
				$BeginNum = $Middle;
			}
		}

		$ipFlag = fread($fd, 1);
		if ($ipFlag == chr(1)) {
			$ipSeek = fread($fd, 3);
			if (strlen($ipSeek) < 3) {
				fclose($fd);
				return array('err' => true, 'msg' => '- System Error');
			}
			$ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
			fseek($fd, $ipSeek);
			$ipFlag = fread($fd, 1);
		}

		if ($ipFlag == chr(2)) {
			$AddrSeek = fread($fd, 3);
			if (strlen($AddrSeek) < 3) {
				fclose($fd);
				return array('err' => true, 'msg' => '- System Error');
			}
			$ipFlag = fread($fd, 1);
			if ($ipFlag == chr(2)) {
				$AddrSeek2 = fread($fd, 3);
				if (strlen($AddrSeek2) < 3) {
					fclose($fd);
					return array('err' => true, 'msg' => '- System Error');
				}
				$AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
				fseek($fd, $AddrSeek2);
			} else {
				fseek($fd, -1, SEEK_CUR);
			}

			while (($char = fread($fd, 1)) != chr(0))
				$ipAddr2 .= $char;

			$AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
			fseek($fd, $AddrSeek);

			while (($char = fread($fd, 1)) != chr(0))
				$ipAddr1 .= $char;
		} else {
			fseek($fd, -1, SEEK_CUR);
			while (($char = fread($fd, 1)) != chr(0))
				$ipAddr1 .= $char;

			$ipFlag = fread($fd, 1);
			if ($ipFlag == chr(2)) {
				$AddrSeek2 = fread($fd, 3);
				if (strlen($AddrSeek2) < 3) {
					fclose($fd);
					return array('err' => true, 'msg' => '- System Error');
				}
				$AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
				fseek($fd, $AddrSeek2);
			} else {
				fseek($fd, -1, SEEK_CUR);
			}
			while (($char = fread($fd, 1)) != chr(0))
				$ipAddr2 .= $char;
		}
		fclose($fd);

		if ($onlyCity) {
			$result = $ipAddr1;
		} else {
			if (preg_match('/http/i', $ipAddr2)) {
				$ipAddr2 = '';
			}
			$ipaddr = "$ipAddr1 $ipAddr2";
			$ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
			$ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
			$ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
			if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
				$ipaddr = '- Unknown';
			}

			$result = '- ' . $ipaddr;
		}

		return mb_convert_encoding($result, "utf-8", "gb2312");
	}

}
